const fs = require('fs');  // fs 模块用于文件操作
const sqlite3 = require('sqlite3').verbose();  // sqlite3 模块用于操作 SQLite
const os = require('os');  // os 模块用于获取本地目录
const NODE_ENV = process.env.NODE_ENV

import { add_tables, add_index, alter_tables } from './Tables'
import Utils from '../../renderer/src/utils/Utils'

const userDir = os.homedir();  // 获取用户目录 C:\Users\用户名
console.log('userDir: ', userDir);
const dbFolder = userDir + (NODE_ENV == 'development' ? '/.r-chat-data/' : '/.r-chat-data/');  // 数据库目录
console.log('dbFolder: ', dbFolder);
if (!fs.existsSync(dbFolder)) {  // 如果目录不存在，则创建
    fs.mkdirSync(dbFolder);  // 创建目录
    console.log('create db folder success: ', dbFolder);;
}

const db = new sqlite3.Database(dbFolder + 'r-chat.db');  // 创建数据库

/* 创建表 */
const createTable = () => {
    // 必须同步执行，先建表再进入应用
    return new Promise(async (resolve, reject) => {
        // 创建表
        for (const item of add_tables) {
            await db.run(item);  // 逐条执行
        }
        // 创建索引
        for (const item of add_index) {
            await db.run(item);  // 逐条执行
        }
        // 修改表
        for (const item of alter_tables) {
            const fieldList = await queryAll(`PRAGMA table_info(${item.table})`);  // 获取字段列表
            const field = fieldList.some(i => i.name == item.field);  // 判断是否包含该字段，没有才执行
            if (!field) {
                await db.run(item.sql);  // 修改表
            }
        }
        resolve();
    })
}

/* 查询全部数据 */
const queryAll = (sql, params) => {
    console.log('queryAll sql: ', sql);
    console.log('queryAll params: ', params);
    return new Promise((resolve, reject) => {
        const stmt = db.prepare(sql);  // 使用预编译语句防止 SQL 注入
        stmt.all(params, (err, rows) => {
            if (err) {
                console.error('queryAll err: ', err);
                resolve([]);
            }
            // 将数据库中每行数据转换为 JSON 格式，同时满足驼峰命名
            rows.forEach((item, index) => {
                rows[index] = convertToJson(item);
            })
            console.log("result: ", rows)
            resolve(rows);  // 返回查询结果
        });
        stmt.finalize();  // 释放预编译语句，防止内存泄漏
    })
}

/* 查询单条数据 */
const queryOne = (sql, params) => {
    console.log('queryOne sql: ', sql);
    console.log('queryOne params: ', params);
    return new Promise((resolve, reject) => {
        const stmt = db.prepare(sql);  // 使用预编译语句防止 SQL 注入
        stmt.get(params, (err, row) => {
            if (err) {
                console.error('queryOne err: ', err);
                resolve({});
            }
            row = convertToJson(row)  // 直接将数据转换为 JSON 格式
            console.log("result: ", row)
            resolve(row);
        });
        stmt.finalize();  // 释放预编译语句，防止内存泄漏
    })
}

/* 查询记录数 */
const queryCount = (sql, params) => {
    console.log('queryCount sql: ', sql);
    console.log('queryCount params: ', params);
    return new Promise((resolve, reject) => {
        const stmt = db.prepare(sql);  // 使用预编译语句防止 SQL 注入
        stmt.get(params, (err, rows) => {
            if (err) {
                console.error('queryCount err: ', err);
                resolve(0);
            }
            const count = Array.from(Object.values(rows))[0]  // count也是一条数据，取第0个值就是count
            resolve(count);
        });
        stmt.finalize();  // 释放预编译语句，防止内存泄漏
    })
}

/* 增删改直接执行的函数 */
const run = (sql, params) => {
    return new Promise((resolve, reject) => {
        const stmt = db.prepare(sql);  // 使用预编译语句防止 SQL 注入
        stmt.run(params, function (err, rows) {
            console.log('run sql: ', sql);
            console.log('run params: ', params);
            if (err) {
                console.error('run err: ', err);
                resolve("sql error");
            }
            console.log('run success. changes: ', this.changes);
            resolve(this.changes);  // 返回影响的行数
        });
        stmt.finalize();  // 释放预编译语句，防止内存泄漏
    })
}

/* 插入数据 */
const insert = (sqlPrefix, tableName, data) => {
    const columnsMap = globalColumnsMap[tableName];  // 获取该表对应的字段名映射
    const dbColumns = [];  // 插入的字段名
    const params = [];  // 插入的参数
    for (let item in data) {
        if (data[item] != undefined && columnsMap[item] != undefined) {
            dbColumns.push(columnsMap[item]);  // 插入的字段名
            params.push(data[item]);  // 插入的参数
        }
    }
    // 拼接 ?,?,? 这样的字符串
    const preparedSql = "?".repeat(dbColumns.length).split('').join(',');
    // 拼接 sql
    const sql = `${sqlPrefix} ${tableName} (${dbColumns.join(',')}) values (${preparedSql})`;
    return run(sql, params);
}

/* 新增或更新数据 */
const insertOrReplace = (tableName, data) => {
    return insert('insert or replace into', tableName, data);
}

/* 不存在才新增数据 */
const insertOrIgnore = (tableName, data) => {
    return insert('insert or ignore into', tableName, data);
}

/* 更新数据 */
const update = (tableName, data, paramData) => {
    const columnsMap = globalColumnsMap[tableName];  // 获取该表对应的字段名映射
    const dbColumns = [];  // 更新的字段名
    const params = [];  // 更新的参数
    const whereColumns = [];  // where 条件字段名
    for (let item in data) {
        if (data[item] != undefined && columnsMap[item] != undefined) {
            dbColumns.push(`${columnsMap[item]}=?`);  // 更新的字段名  set 字段名=?
            params.push(data[item]);  // 更新的参数 上面?的实际填充值
        }
    }
    for (let item in paramData) {
        if (paramData[item] != undefined && columnsMap[item] != undefined) {
            whereColumns.push(`${columnsMap[item]}=?`);  // where条件字段名 where 字段名=?
            params.push(paramData[item]);  // 上面?的实际填充值
        }
    }
    // 拼接 sql
    const sql = `update ${tableName} set ${dbColumns.join(', ')} ${whereColumns.length > 0 ? 'where' : ''} ${whereColumns.join(' and ')}`;
    return run(sql, params);
}

/* 将数据库中每行数据转换为 JSON 格式 */
const convertToJson = (data) => {
    if (!data || data.length === 0) return null;
    const jsonData = {}
    for (let item in data) {
        // 字段名要转为驼峰命名
        jsonData[Utils.toCamelCase(item)] = data[item];
    }
    return jsonData;
};

/* 获取 所有表的字段名的驼峰格式 到 所有表的字段名 的映射 */
const globalColumnsMap = {};
/* 
globalColumnsMap:  {
  chat_message: {
    userId: 'user_id',
    messageId: 'message_id',
    ......
  },
  ......
}
*/
const getGlobalColumnsMap = async () => {
    // 获取所有表
    let sql = `select name from sqlite_master where type='table' and name not in ('sqlite_sequence')`;
    let tables = await queryAll(sql);
    for (let i = 0; i < tables.length; i++) {
        // 获取每张表的字段名
        sql = `PRAGMA table_info(${tables[i].name})`;
        let columns = await queryAll(sql);
        const columnsMap = {};
        // 将每张表的字段名转为驼峰格式，并保存到映射中
        for (let j = 0; j < columns.length; j++) {
            columnsMap[Utils.toCamelCase(columns[j].name)] = columns[j].name;
        }
        // 将每张表的映射保存到全局映射中
        globalColumnsMap[tables[i].name] = columnsMap;
    }
    // console.log('globalColumnsMap: ', globalColumnsMap);
}

const init = () => {
    db.serialize(async () => {
        await createTable();  // 建立表、索引、修改表
        await getGlobalColumnsMap();  // 获取 所有表的字段名的驼峰格式 到 所有表的字段名 的映射
        console.log('init table success');
    })
}

init();

export {
    run,
    queryAll,
    queryOne,
    queryCount,
    insert,
    insertOrReplace,
    insertOrIgnore,
    update
}